﻿/*
 * @author: wizardc
 */

using System;
using System.Reflection;
using Dou.Resource;
using Dou.Sync;
using Dou.Utils;
using UnityEngine;

namespace Dou
{
    /// <summary>
    /// 游戏入口脚本抽象类
    /// 游戏入口请继承该类实现
    /// </summary>
    public abstract class AbstractGameMain : MonoBehaviour
    {
        public static event Action startEvent;
        public static event Action fixedUpdateEvent;
        public static event Action updateEvent;
        public static event Action lateUpdateEvent;
        public static event Action<bool> onApplicationPauseEvent;
        public static event Action<bool> onApplicationFocusEvent;
        public static event Action onApplicationQuitEvent;
        
        /// <summary>
        /// 是否开启 SRDebugger
        /// </summary>
        public bool openSRDebugger = false;
        
        /// <summary>
        /// 日志打印等级
        /// </summary>
        public LogLevel logLevel = LogLevel.All;
        
        /// <summary>
        /// 是否使用 AB 资源
        /// </summary>
        public bool useAssetBundle = false;
        
        /// <summary>
        /// AB 资源是否加密
        /// </summary>
        public bool isABEncrypt = false;

        /// <summary>
        /// AB 资源卸载配置
        /// </summary>
        public AssetUnloadSetting[] abUnloadSettings;
        
        private int _targetFrameRate = 0;
        
        protected virtual void Awake()
        {
            DontDestroyOnLoad(gameObject);

            if (openSRDebugger)
            {
                SRDebug.Init();
            }
            Log.level = logLevel;
            MainThreadContext.Init();
            CoroutineUtil.Init(this);
            
#if UNITY_EDITOR
            OnEditorInit();
#endif
            
            UnityEngine.U2D.SpriteAtlasManager.atlasRequested += (path, action) => { }; // 防止警告打印
            AssetManager.instance.Init(useAssetBundle ? AssetLoadType.AssetBundle : AssetLoadType.AssetDatabase, isABEncrypt, OnInit, abUnloadSettings);
        }

#if UNITY_EDITOR
        
        /// <summary>
        /// 编辑器环境下启动时需要执行的代码
        /// </summary>
        protected virtual void OnEditorInit()
        {
            // 创建图集配置文件
            try {
                const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
                var assembly = Assembly.Load("DouFrameworkEditor");
                var cls = assembly.GetType("DouEditor.Resource.BuildStep_CreateAtlas");
                var method = cls.GetMethod("Start", bindingFlags);
                method.Invoke(assembly.CreateInstance(cls.FullName), null);
            } catch (Exception e) {
                Debug.LogError(e);
                throw;
            }
        }
        
#endif
        
        protected abstract void OnInit();

        protected virtual void Start()
        {
            startEvent?.Invoke();
        }

        protected virtual void FixedUpdate()
        {
            fixedUpdateEvent?.Invoke();
        }

        protected virtual void Update()
        {
            updateEvent?.Invoke();
        }

        protected virtual void LateUpdate()
        {
            lateUpdateEvent?.Invoke();
        }

        protected virtual void OnApplicationPause(bool pause)
        {
            onApplicationPauseEvent?.Invoke(pause);
            if (pause)
            {
                _targetFrameRate = Application.targetFrameRate;
                Application.targetFrameRate = 1;
            }
            else
            {
                Application.targetFrameRate = _targetFrameRate;
            }
        }

        protected virtual void OnApplicationFocus(bool focus)
        {
            onApplicationFocusEvent?.Invoke(focus);
        }

        protected virtual void OnApplicationQuit()
        {
            onApplicationQuitEvent?.Invoke();
        }
        
        /// <summary>
        /// 退出应用
        /// </summary>
        public void QuitApp()
        {
#if UNITY_EDITOR
            UnityEditor.EditorApplication.isPlaying = false;
#else
            Application.Quit();
#endif
        }
    }
}
